using GLib;

public enum LogCategary
{
    SUCCESS,
    FAIL
}

public class Logger : GLib.Object
{
    private File file;
    private string directory = null;
    private string succ_dir = null;
    private string fail_dir = null;
    private FileOutputStream os;
 
    public string name { get; construct set; }   
    
    public Logger(string name, string? directory)
    {
        string file_name = null;
        
        if(null == directory)
        {
            file_name = Path.build_path(Path.DIR_SEPARATOR_S, Path.get_dirname(name), Path.get_basename(name).replace(".c", ".log"));
        }
        else
        {
            file_name = Path.build_path(Path.DIR_SEPARATOR_S, directory, Path.get_basename(name).replace(".c", ".log"));
            
            this.succ_dir = Path.build_path(Path.DIR_SEPARATOR_S, directory, "Success");
        
            this.fail_dir = Path.build_path(Path.DIR_SEPARATOR_S, directory, "Fail");
            
            if(FileUtils.test(succ_dir, FileTest.EXISTS))
            {
                if(!FileUtils.test(succ_dir, FileTest.IS_DIR))
                {
                    FileUtils.remove(succ_dir);
                }
            }
            else
            {
                DirUtils.create(succ_dir, 0777);
            }
            if(FileUtils.test(fail_dir, FileTest.EXISTS))
            {
                if(!FileUtils.test(fail_dir, FileTest.IS_DIR))
                {
                    FileUtils.remove(fail_dir);
                }
            }
            else
            {
                DirUtils.create(fail_dir, 0777);
            }
            
            this.directory = directory;
        }
                
        Object(name : file_name);
        
        try
        {     
            this.file = File.new_for_path(file_name);
            
            if(file.query_exists())
            {
                try
                {
                    file.@delete();
                }
                catch(Error error)
                {
                    print("delete file fail, %s\n", error.message);
                }
            }
            
            this.os =  file.create(FileCreateFlags.NONE);
        }
        catch(Error error)
        {
            print("%s\n", error.message);
        }     
    }
    
    public void write(string message)
    {
        size_t bytes_written = 0;
        string tmp;
        
        tmp = message;
        
        if(!message.has_suffix("\n"))
        {
            tmp += "\n";
        }
        
        try
        {
            GLib.stdout.write(tmp.data);
            
            os.write_all (tmp.data, out bytes_written);
        }
        catch(IOError error)
        {
            print("%s\n", error.message);
        }
    }
    
    public void write_data(uint8[] data)
    {
        size_t bytes_written = 0;
        
        try
        {
            GLib.stdout.write(data);
            
            GLib.stdout.write("\n".data);
            
            os.write_all (data, out bytes_written);
            
            os.write_all ("\n".data, out bytes_written);
        }
        catch(IOError error)
        {
            print("%s\n", error.message);
        }
    }
    
    public void @set_category(LogCategary categary)
    {
        File file = null;
        
        if(null == this.directory)
        {
            return;
        }
        
        switch(categary)
        {
            case LogCategary.SUCCESS:
                file = File.new_for_path(Path.build_path(Path.DIR_SEPARATOR_S, this.succ_dir, Path.get_basename(this.file.get_path())));
                break;
                
            case LogCategary.FAIL:
                file = File.new_for_path(Path.build_path(Path.DIR_SEPARATOR_S, this.fail_dir, Path.get_basename(this.file.get_path())));
                break;
        }
        
        try
        {
            this.file.move(file, FileCopyFlags.OVERWRITE);
        }
        catch(Error error)
        {
            print("logger move file fail, %s\n", error.message);
        }
    }
}
